#include "window.hpp"
#include <cstring>
#include <new>
#include "debug.hpp"

namespace fur
{
   Window::Window(size_t buffsize) throw(Exception)
   try
   {
      data = new uint8_t[buffsize];
      position = 0;
      maxsize = buffsize;
   }
   catch (std::bad_alloc)
   {
      throw EAllocation(__func__);
   }

   Window::~Window() throw()
   {
      delete [] data;
   }
   
   void Window::copy_string(size_t distance, size_t size) throw()
   {
      size_t srcposi = (maxsize + position - distance) % maxsize;
      size_t endposi = (srcposi + size) % maxsize;
      size_t lastposi = (position + size) % maxsize;
      if (srcposi < position)
      {
	 if (lastposi > position)
	 {
	    if (endposi > position)
	    {
	       while (srcposi != endposi)
	       {
		  data[position] = data[srcposi];
		  ++position;
		  ++srcposi;
	       }
	    }
	    else
	    {
	       memcpy(data + position, data + srcposi, size);
	       position = lastposi;
	    }
	 }
	 else
	 {
	    while (srcposi != endposi)
	    {
	       data[position] = data[srcposi];
	       ++position;
	       position %= maxsize;
	       ++srcposi;
	       srcposi %= maxsize;
	    }
	 }
      }// if (srcposi < position) {
      else
      {
	 if (endposi > srcposi)
	 {
	    memcpy(data + position, data + srcposi, size);
	    position = lastposi;
	 }
	 else
	 {
	    memcpy(data + position, data + srcposi, maxsize - srcposi);
	    position += maxsize - srcposi;
	    if (lastposi > position)
	    {
	       memcpy(data + position, data, endposi);
	       position = lastposi;
	    }
	    else
	    {
	       for (size_t i = 0; i != endposi; ++i)
	       {
		  data[position] = data[i];
		  ++position;
		  position %= maxsize;
	       }
	    }
	 }
      }// if (srcposi < position) ... else {
   }
} // end of namespace fur
